﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Genuilder.Extensibility
{

	public class ExtensionCollection : List<IExtension>
	{
		public T Add<T>(T extension) where T : IExtension
		{
			base.Add(extension);
			return extension;
		}
	}
	public class GenEngineStartInfo
	{
		public String Project
		{
			get;
			set;
		}
		public RunHistory RunHistory
		{
			get;
			set;
		}
		public String GenerationDirectory
		{
			get;
			set;
		}

		internal string CreateGeneratedChildName(string childName)
		{
			if(GenerationDirectory == ".")
				return childName;
			return Path.Combine(GenerationDirectory, childName);
		}
	}


	public class SourceFileCollection : List<SourceFile>
	{
		public void AddRange(IEnumerable<string> sources)
		{
			AddRange(sources.Select(s => new SourceFile(s, SourceType.Compile)));
		}
	}

	public class GenEngine
	{
		public GenEngine()
		{
			StartInfo.GenerationDirectory = ".";
			Logger = new NullGenLogger();
		}
		public bool BuildingInsideVisualStudio
		{
			get;
			set;
		}
		public IGenLogger Logger
		{
			get;
			set;
		}

		private readonly GenEngineStartInfo _StartInfo = new GenEngineStartInfo();
		public GenEngineStartInfo StartInfo
		{
			get
			{
				return _StartInfo;
			}
		}

		readonly SourceFileCollection _SourceFiles = new SourceFileCollection();
		public SourceFileCollection SourceFiles
		{
			get
			{
				return _SourceFiles;
			}
		}

		private readonly ExtensionCollection _Extensions = new ExtensionCollection();
		public ExtensionCollection Extensions
		{
			get
			{
				return _Extensions;
			}
		}



		public RunResult Run(bool @throw = false)
		{
			AssertDirectoryExist();
			var executionContext = new ExecutionContext(SourceFiles, StartInfo, Logger ?? new NullGenLogger());
			foreach(var extension in Extensions)
			{
				var extensionContext = executionContext.CreateExtensionContext(extension);
				extensionContext.BuildingInsideVisualStudio = BuildingInsideVisualStudio;
				try
				{
					extension.Execute(extensionContext);
				}
				catch(Exception ex)
				{
					if(@throw)
						throw;
					return new RunResult(new RunResultError(ex, extensionContext), executionContext);
				}
			}
			return new RunResult(executionContext);
		}

		private void AssertDirectoryExist()
		{
			if(StartInfo.GenerationDirectory == null)
				throw new ArgumentNullException("StartInfo.GenerationDirectory");
			if(!Directory.Exists(StartInfo.GenerationDirectory))
			{
				throw new InvalidOperationException("StartInfo.GenerationDirectory does not exist");
			}
		}

		
	}
}
